#ifndef MODULES_CORE_IOCSERVICE_H_
#define MODULES_CORE_IOCSERVICE_H_
#include "../common.h"

#define GET_BEAN(MODEL,CLASS) \
reinterpret_cast<CLASS*>(IocService::getBean(MODEL))
/***
 * 注入字段
 * @param field1 模块名 @link BeanKey
 * @param field2 字段名
 * */
#define injection_field(...) 	\
		void ____injection_field(){					\
			size_t size = StringSplit(#__VA_ARGS__).size();\
			if(size<=0) return;							\
	 		____injection_fieldA(size,__VA_ARGS__);		\
		 };
/***
 * 自动注册bean
 * @param name 模块名
 * @param clsName 类名
 * */
#define auto_register(name,clzName)
//#define auto_register(name,clzName) \
//		clzName(){		\
//				____register_bean();\
//		}							\
//		void ____register_bean(){		\
// 			IocService::registerBean(name,this); \
//		}
#define app_injection_bean(name,clzName) \
				App.p##clzName= new clzName; \
				IocService::registerBean(name,App.p##clzName);
#define app_create_field(clzName) \
				clzName * p##clzName;

template<typename STR, typename TYPE, typename ... TYPES>
static void ____injection_fieldA(size_t &size, STR name, TYPE &field, TYPES &...args) {
	____injection_fieldA(size, name, field);
	if (size <= 0)
		return;
	____injection_fieldA(size, args...);
}

static std::vector<std::string> StringSplit(const std::string &str, char sep = ',') {
	std::vector<std::string> array;
	std::string::size_type pos1, pos2;
	pos1 = 0;
	pos2 = str.find(sep);
	while (std::string::npos != pos2) {
		array.push_back(str.substr(pos1, pos2 - pos1));
		pos1 = pos2 + 1;
		pos2 = str.find(sep, pos1);
	}
	if (pos1 != str.length())
		array.push_back(str.substr(pos1));
	return array;
}

class IocService {
public:
	void init();
	void prepare0();
	void prepare();
	void start();
	void restart();
	void close();
	void loop();
	void injectionField();
	static IBean* getBean(BeanKey key) ;
	static void registerBean(BeanKey key, IBean *bean) ;
};


template<typename STR, typename TYPE>
static void ____injection_fieldA(size_t &size, STR name, TYPE &field) {
	size = size - 2;
	IBean *f = IocService::getBean(name);
	if (f  == nullptr)
		throw "injection_field notfind bean: ";
	//http://c.biancheng.net/view/410.html
	//-fno-rtti  出现这个提示，把运行参数去掉
	field = reinterpret_cast<TYPE>(f);
}
extern IocService iocService;
#endif /* MODULES_CORE_IOCSERVICE_H_ */
